#ifndef MDIST_URL_COMM_H
#define MDIST_URL_COMM_H

#include <time.h>
#include <stdlib.h>
#include <string.h>
#define REGULAR_MAX_LEN 1024
#define CUR_VERSION 0x01
typedef struct {
	unsigned short version;
	char cmd[20];
	time_t timestamp;
	int num;
	char regular[REGULAR_MAX_LEN];
}DIST_URL_PROTO_CLIENT;

static inline int init_struct_client(DIST_URL_PROTO_CLIENT *c, int num, const char *regular)
{
	if (!c)
		return -1;
	c->version = CUR_VERSION;
	strcpy(c->cmd, "GETURL");
	c->timestamp = time(NULL);
	c->num = num;
	if (!regular || strlen(regular) >= REGULAR_MAX_LEN) 
		return -1;
	strcpy(c->regular, regular);
	return 0;
}

static inline char *struct2str_client(const DIST_URL_PROTO_CLIENT *c)
{
	if (!c)
		return NULL;
	int buf_len = 5 + strlen(c->cmd) + 15 + 10 + strlen(c->regular) + 10;
	char *buf = (char *)malloc(buf_len);
	sprintf(buf, "%hu %s %lu %d %s\n", c->version, c->cmd, c->timestamp, c->num, c->regular);
	return buf;
}

typedef struct {
	unsigned short version;
	time_t timestamp;
	int seral;	//从1开始的序号，递增，0表示结束, 如果timestamp相同，则为相同的应答，需讲多个UDP包合并后返回
	char data[1];
}DIST_URL_PROTO_SERVER;

/*
 * return:	-1 some error, or seral;
 * */
static inline int str2struct_server(DIST_URL_PROTO_SERVER **s, const char *buf)
{
	if (buf == NULL) {
		*s = NULL;
		return 0;
	}
	DIST_URL_PROTO_SERVER *st = (DIST_URL_PROTO_SERVER *)malloc(strlen(buf) * sizeof(DIST_URL_PROTO_SERVER));
	if (sscanf(buf, "%hu %lu %d", &st->version, &st->timestamp, &st->seral) != 3) {
		free(st);
		*s = NULL;
		return -1;
	}
	char *line2 = strchr(buf, '\n');
	if (!line2 || (line2 + 1) == (buf + strlen(buf)))
		st->data[0] = '\0';
	else
		strcpy(st->data, line2 + 1);
	*s = st;
	return st->seral;
}

#define INCREASE_STEP 10
typedef struct {
	int array_len;
	int end_index;
	DIST_URL_PROTO_SERVER **start;
	char *full_data;
}DIST_URL_SERVER_HANDLE;

static inline int compar(const void *a, const void *b)
{
	DIST_URL_PROTO_SERVER **s1 = (DIST_URL_PROTO_SERVER **)a;
	DIST_URL_PROTO_SERVER **s2 = (DIST_URL_PROTO_SERVER **)b;
	return (*s1)->seral - (*s2)->seral;
}

void destroy_server_handle(DIST_URL_SERVER_HANDLE *h)
{
	if (!h)
		return;
	if (h->start) {
		for (int i = 0; i < h->end_index; i++) {
			if (h->start[i])
				free(h->start[i]);
		}
	}
	if (h->full_data)
		free(h->full_data);
}

/*
 * 如果收包完毕，则返回1，未完毕返回0，出错返回-1
 * */
static inline int add_s_pack(DIST_URL_SERVER_HANDLE *h, DIST_URL_PROTO_SERVER *s)
{
	DIST_URL_SERVER_HANDLE *handle = NULL;
	if (h == NULL) {
		return -1;
	}
	else handle = h;

	if (handle->end_index >= handle->array_len) {
		handle->start = (DIST_URL_PROTO_SERVER **)realloc(handle->start, handle->array_len + INCREASE_STEP);
		handle->array_len += INCREASE_STEP;
	}
	handle->start[handle->end_index] = s;
	handle->end_index++;
	if (s->seral == 0) {
		/*
		 * 对handle->start按seral进行排序,从小到大排序,序号0(最后一个包)排在第一个
		 * */
		qsort(handle->start, handle->end_index, sizeof(DIST_URL_PROTO_SERVER *), compar);

		/*
		 * 合并UDP包, 未检查版本号、时间戳以及序号是否连续等内容
		 * */
		int len = 0;
		for (int i = 0; i < handle->end_index; i++) {
			len += strlen(handle->start[i]->data);
		}
		handle->full_data = (char *)malloc(len + 10);
		handle->full_data[0] = '\0';
		for (int i = 1; i < handle->end_index; i++) {
			strcat(handle->full_data, handle->start[i]->data);
		}
		strcat(handle->full_data, handle->start[0]->data);
		return 1;
	}
	return 0;
}

#endif
